package org.particlethink.controller;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.particlethink.auth.DefaultUser;
import org.particlethink.context.DefaultContext;
import org.particlethink.entry.OrderStatus;
import org.particlethink.mapper.*;
import org.particlethink.model.*;
import org.particlethink.request.OrderReCreateRequest;
import org.particlethink.request.ReasonRequest;
import org.particlethink.request.RefuseReasonRequest;
import org.particlethink.request.RemarkRequest;
import org.particlethink.response.*;
import org.particlethink.service.procure.ProjectUserImpl;
import org.particlethink.service.procure.SupplierUserImpl;
import org.particlethink.utils.ListUtilsKt;
import org.particlethink.utils.ObjectUtilsKt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Tag(name = "订单")
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    ProjectUserImpl projectUserSvc;
    @Autowired
    SupplierUserImpl supplierUserSvc;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private DeliverMapper deliverMapper;


    @Autowired
    private ProjectUserMapper projectUserMapper;
    @Autowired
    private SupplierMapper supplierMapper;
    @Autowired
    private SupplierUserMapper supplierUserMapper;

    private final static Logger logger = LoggerFactory.getLogger(OrderController.class);


    @Operation(summary = "订单列表")
    @GetMapping
    public BaseResponse<PageInfo<OrderResponse>> List(
            @Parameter(description = "管理层级 string")
            @RequestParam(value = "managementLevel", required = false)
            String managementLevel,

            @Parameter(description = "项目id int")
            @RequestParam(value = "projectId", required = false)
            Integer projectId,

            @Parameter(description = "订单标号 String")
            @RequestParam(value = "orderNo", required = false)
            String orderNo,

            @Parameter(description = "批次计划编号 String")
            @RequestParam(value = "batchPlanNo", required = false)
            String batchPlanNo,

            @Parameter(description = "物料大类名 string")
            @RequestParam(value = "categoryName", required = false)
            String categoryName,

            @Parameter(description = "创建人名 string")
            @RequestParam(value = "creatorName", required = false)
            String creatorName,

            @Parameter(description = "状态 int 1:待发货 ;2:异常退回 ;3:进行中 ;4:已完成")
            @RequestParam(value = "status", required = false)
            OrderStatus status,

            @Parameter(description = "提交开始时间 string yyyy-MM-dd HH:mm:ss")
            @RequestParam(value = "submitStart", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitStart,
            @Parameter(description = "提交结束时间 string")
            @RequestParam(value = "submitEnd", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitEnd,

            @Parameter(description = "搜索key string")
            @RequestParam(value = "searchKey", required = false)
            String searchKey,

            @Parameter(description = "页码 int")
            @RequestParam(value = "pageNum", required = false)
            Integer pageNum,
            @Parameter(description = "每页数量 int")
            @RequestParam(value = "pageSize", required = false)
            Integer pageSize
    ) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        if (searchKey != null && !searchKey.isEmpty()) {
            PageInfo<OrderResponse> orderResponses1 = projectUserSvc.orderByNo(user, status, searchKey);
            if (orderResponses1 != null && !orderResponses1.getList().isEmpty()) {
                return BaseResponse.success(orderResponses1);
            }
        }


        PageInfo<OrderResponse> orderResponses = projectUserSvc.orderList(
                defaultUser,
                managementLevel,
                projectId,
                orderNo,
                batchPlanNo,
                categoryName,
                creatorName,
                status,
                submitStart,
                submitEnd,
                searchKey,
                pageNum,
                pageSize
        );


        return BaseResponse.success(orderResponses);
    }

    @Operation(summary = "订单导出")
    @GetMapping("/export")
    public void export(
            @Parameter(description = "管理层级 string")
            @RequestParam(value = "managementLevel", required = false)
            String managementLevel,

            @Parameter(description = "项目id Integer")
            @RequestParam(value = "projectId", required = false)
            Integer projectId,

            @Parameter(description = "订单标号 String")
            @RequestParam(value = "orderNo", required = false)
            String orderNo,

            @Parameter(description = "批次计划编号 String")
            @RequestParam(value = "batchPlanNo", required = false)
            String batchPlanNo,

            @Parameter(description = "物料大类名 string")
            @RequestParam(value = "categoryName", required = false)
            String categoryName,

            @Parameter(description = "创建人名 string")
            @RequestParam(value = "creatorName", required = false)
            String creatorName,

            @Parameter(description = "状态 int 1:待发货 ;2:异常退回 ;3:进行中 ;4:已完成")
            @RequestParam(value = "status", required = false)
            OrderStatus status,

            @Parameter(description = "提交开始时间 string yyyy-MM-dd HH:mm:ss")
            @RequestParam(value = "submitStart", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitStart,
            @Parameter(description = "提交结束时间 string")
            @RequestParam(value = "submitEnd", required = false)
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            Date submitEnd,

            HttpServletResponse response
    ) throws IOException {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();
        List<OrderExportResponse> orderResponses = projectUserSvc.orderExport(
                user,
                managementLevel,
                projectId,
                orderNo,
                batchPlanNo,
                categoryName,
                creatorName,
                status,
                submitStart,
                submitEnd
        );


        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("订单", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        EasyExcel.write(response.getOutputStream(), OrderExportResponse.class).sheet("模板").doWrite(orderResponses);

    }

    @Operation(summary = "订单详情")
    @GetMapping("/{id}")
    public BaseResponse<OrderDetailResponse> Show(@PathVariable("id") Integer id) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        OrderDetailResponse orderDetailResponse = projectUserSvc.orderDetail(user, id);
        return BaseResponse.success(orderDetailResponse);
    }

    @Operation(summary = "撤回订单")
    @PostMapping("/{id}/cancel")
    public BaseResponse<String> cancel(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.cancelOrder(user.getProjectIds(), id);

        return BaseResponse.success("");
    }

    @Operation(summary = "备注订单")
    @PostMapping("/{id}/remark")
    public BaseResponse<String> remark(
            @PathVariable("id")
            Integer id,
            @Parameter(description = "remark string")
            @RequestBody RemarkRequest reason
//            @RequestParam(value = "remark", required = true)
    ) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.remarkOrder(user.getProjectIds(), id, reason.getRemark());

        return BaseResponse.success("");
    }

    @Operation(summary = "终止发货")
    @PostMapping("/{id}/stop")
    public BaseResponse<String> stopDelivery(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();
        projectUserSvc.stopDelivery(user.getProjectIds(), id);

        return BaseResponse.success("");
    }

    @Operation(summary = "完成发货")
    @PostMapping("/{id}/complete")
    public BaseResponse<String> complete(@PathVariable("id") Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();
        supplierUserSvc.complete(user.getSupplierIds(), id);

        return BaseResponse.success("");
    }


    @Operation(summary = "重新发起")
    @PostMapping("/{id}/reCreate")
    public BaseResponse<String> reCreateOrder(
            @PathVariable("id") Integer id,
            @Parameter(description = "拒绝原因 string")
            @RequestBody(required = false) OrderReCreateRequest request) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        projectUserSvc.reCreateOrder(user.getProjectIds(), request.getSupplierId(), id);

        return BaseResponse.success("");
    }


    @Operation(summary = "订单流程")
    @GetMapping("/{id}/status")
    public BaseResponse<List<OrderStatusResponse.Status>> status(@PathVariable("id") Integer id) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        Order order = orderMapper.selectByPrimaryKey(id);

        ProjectUser projectUser = projectUserMapper.selectByPrimaryKey(order.getCreatorId());

        List<OrderStatusResponse.Status> statusList = new ArrayList<>();
        if (order.isUnshipped()) {
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Unshipped, projectUser.getName(), order.getCreatedAt(), "", true));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.InProgress, "", null, ""));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Done, "", null, ""));
        }

        if (order.isRefused()) {
            String handleUsername = null;
            switch (order.getRefuseUserType()) {
                case Supplier:
                    handleUsername = supplierUserMapper.selectByPrimaryKey(order.getRefuseUserId()).getName();
                    break;
                case Project:
                    handleUsername = projectUserMapper.selectByPrimaryKey(order.getRefuseUserId()).getName();
            }
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Unshipped, projectUser.getName(), order.getCreatedAt(), ""));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Refuse, handleUsername, order.getRefuseDate(), "", true));
        }

        if (order.isInProgress()) {
            Deliver deliver = ListUtilsKt.max(deliverMapper.selectByOrderId(id), Deliver::getCreatedAt).orElseGet(Deliver::new);
            Supplier supplier = supplierMapper.selectById(user.getToken(), deliver.getSupplierId());
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Unshipped, projectUser.getName(), order.getCreatedAt(), ""));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.InProgress, ObjectUtilsKt.defaultIfNull(supplier, new Supplier()).getName(), deliver.getCreatedAt(), "", true));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Done, "", null, ""));
        }

        if (order.isDone()) {
            List<Deliver> delivers = deliverMapper.selectByOrderId(id);

            Deliver deliver = ListUtilsKt.max(delivers, Deliver::getCreatedAt).orElseGet(Deliver::new);
            Supplier supplier = supplierMapper.selectById(user.getToken(), deliver.getSupplierId());

            Deliver lastComplateDeliver = ListUtilsKt.max(delivers.stream().filter(Deliver::isComplete).collect(Collectors.toList()), Deliver::getAcceptanceAt).orElseGet(Deliver::new);
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Unshipped, projectUser.getName(), order.getCreatedAt(), ""));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.InProgress, ObjectUtilsKt.defaultIfNull(supplier, new Supplier()).getName(), deliver.getCreatedAt(), ""));
            statusList.add(new OrderStatusResponse.Status(OrderStatus.Done, ObjectUtilsKt.defaultIfNull(supplier, new Supplier()).getName(), lastComplateDeliver.getAcceptanceAt(), "", true));
        }
        //todo
        return BaseResponse.success(statusList);
    }


    @Operation(summary = "拒单")
    @PostMapping("/{id}/refuse")
    public BaseResponse<String> refuse(
            @PathVariable("id")
            Integer id,
            @Parameter(description = "拒绝原因 string")
            @RequestBody(required = false) RefuseReasonRequest refuseReason
    ) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        supplierUserSvc.refuse(user.getSupplierIds(), id, refuseReason == null ? "" : refuseReason.getRefuseReason());


        return BaseResponse.success("");
    }
    //小程序

    @Operation(summary = "订单状态对应数量")
    @GetMapping("/status_count")
    public BaseResponse<OrderStatusCountResponse> statusCount(
    ) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        List<Integer> supplierIds = user.getSupplierIds();
        List<Integer> projectIds = user.getProjectIds();

        OrderStatusCountResponse orderStatusCountResponses = supplierUserSvc.countOrdersByStatus(supplierIds, projectIds);
        return BaseResponse.success(orderStatusCountResponses);
    }

}
